/******************************************************************************
 * Author:      671643387
 * Created:     2016/10/26
 *****************************************************************************/

var util            = require("util");
var Enum            = require("./Enum.js");
var ProtoID         = require("../../../net/ProtoID.js").ProtoID;
var ProtoState      = require("../../../net/ProtoID.js").ProtoState;
var Opcodes         = require("./Opcodes.js").Opcodes;
var CheckFunc       = require("./function.js");

///////////////////////////////////////////////////////////////////////////////
//>> 玩家手牌

function HandCards(owner) {
    this.owner  = owner;

    this.num    = 0;
    this.cards  = [];   // 手牌
    this.PENGs  = [];   // 碰
    this.GANGs  = [];   // 杠
    this.chiInfo = [];  // 吃牌信息

    this.init(owner.owner.selectWind);
}

HandCards.prototype = {

    // 初始化
    init: function (selectWind) {
        var maxCard = 0;
        if(selectWind){
            maxCard = Enum.MAX_CARDS_WIND;
        }else {
            maxCard = Enum.MAX_CARDS_NOT_WIND;
        }
        // 初始化结构
        for (var iCard = 0; iCard < maxCard; ++iCard) {
            this.cards[iCard] = {
                value : iCard + 1,
                num : 0,
            };
        }
        this.num = 0;
        this.PENGs  = [];   // 碰
        this.GANGs  = [];   // 杠
        this.chiInfo = [];  // 吃牌信息
    },

    // 重置
    reset: function() {
        this.init(this.owner.owner.selectWind);
    },

    // 添加手牌
    adds: function(cards) {
        var _me = this;
        cards.forEach(function(card){
            var value = (card.type - 1) * 9 + card.value;
            var newCard = _me.cards[value - 1];
            newCard.num += 1;
            _me.cards[value - 1] = newCard;
            _me.num += 1;
        });
    },
    // 增加手牌
    add: function(card, num) {
        num = num || 1;
        var myCard = this.cards[card - 1];
        myCard.num += num;
        this.num += num;
    },

    // 获取手牌有几个和这张牌一样的牌
    hasSame: function(card) {
        var myCard = this.cards[card - 1];
        return myCard.num;
    },
    getMixCardNum:function (mixCard) {
        return this.cards[mixCard - 1].num;
    },
    // 检查胡牌玩家的根
    getHasBeltRootNum : function () {
        var num = 0;
        this.add(this.owner.huCard);
        for(var pos in this.cards){
            if(!this.cards.hasOwnProperty(pos)){
                continue;
            }
            if(this.cards[pos].num == 4){
                ++num;
            }
        }
        this.decCard(this.owner.huCard, 1);
        return num;
    },
    getSynEffectiveIdx: function () {
        var num = 0;
        for(var pos in this.cards){
            if(!this.cards.hasOwnProperty(pos)){
                continue;
            }
            if(this.cards[pos].num>0){
                ++num;
            }
        }
        return num;
    },
    getSynEffectiveData: function () {
        var cards = [];
        for(var pos in this.cards){
            if(!this.cards.hasOwnProperty(pos)){
                continue;
            }
            if(this.cards[pos].num>0){
                cards.push(this.cards[pos]);
            }
        }
        return cards;
    },
    // 吃牌，
    hasEatCard: function(curMaJang, cards) {

        // 当前打出的牌不为空，   27以上是 东南西北中发白板 不能吃
        if(!curMaJang || !cards || curMaJang > 27 || cards.value1 > 27 || cards.value2 > 27 || cards.value3 > 27){
            return false;
        }
        // 吃牌当中没有一张是当前打出去的牌， 则出错
        if(curMaJang != cards.value1 && curMaJang != cards.value2 && curMaJang != cards.value3 ){
            return false;
        }
        // 不同一花色不可吃
        if(parseInt((cards.value1 - 1) / 9) != parseInt((cards.value2 - 1) / 9) || parseInt((cards.value1 - 1) / 9) != parseInt((cards.value3 - 1) / 9)){
            return false;
        }
        // 除去当前打出的牌 检查手牌中有没有这张牌
        if(curMaJang != cards.value1 && this.hasSame(cards.value1) < 1){
            return false;
        }
        // 除去当前打出的牌 检查手牌中有没有这张牌
        if(curMaJang != cards.value2 && this.hasSame(cards.value2) < 1){
            return false;
        }
        // 除去当前打出的牌 检查手牌中有没有这张牌
        if(curMaJang != cards.value3 && this.hasSame(cards.value3) < 1){
            return false;
        }

        return true;
    },

    // 减少手牌
    decCard: function(card, num) {
        var myCard = this.cards[card - 1];
        myCard.num -= num;
        this.num -= num;
    },

    // 获取卡牌结算信息
    getHandCardInfo: function(me) {
        return {
            cards   : this.getSync(me),
            pengs   : this.PENGs,
            gangs   : this.GANGs,
            chiInfo : this.chiInfo,
        };
    },

    // 获取卡片数量
    getCardsNum: function() {
        return this.num;
    },

    getSync: function(me) {
        var cards = [];
        if(me && this.num > 0){
            cards = this.cards;
        }
        return { cards: cards, num: this.num };
    },
    // 获取手牌同步数据
    getSyncData: function() {
        return this.cards;
    },

    addPeng: function(card) {
        this.PENGs.push({
            value   : card,
        });
    },

    // 减少碰牌
    decPengCard: function(card) {
        var index  = -1;
        for(var pos in this.PENGs){
            if(!this.PENGs.hasOwnProperty(pos)){
                continue;
            }
            var temp = this.PENGs[pos];
            if(temp && temp.value == card){
                index = +pos;
                break;
            }
        }
        if(-1 != index) {
            this.PENGs.splice(index, 1);
        }
    },

    addGang: function(card, mark, owner) {
        this.GANGs.push({
            value   : card,
            mark    : mark,
            owner   : owner,
        });
    },

    addChi: function(card, owner) {
        this.chiInfo.push({
            value1   : card.value1,
            value2   : card.value2,
            value3   : card.value3,
            owner   : owner,
        });
    },

    // 能否碰牌
    checkPeng: function(card) {
       /* var flag = false;
        flag = this.cards[card - 1].num >= 2;
        for(var pos = 0; pos < this.cards.length; pos++){
            this.cards
        }
        if(){

        }*/
        return (this.cards[card - 1].num >= 2);
    },

    checkAddGang: function (card) {
        var flag = false;
        for(var pos in this.PENGs){
            if(!this.PENGs.hasOwnProperty(pos)){
                continue;
            }
            var temp = this.PENGs[pos];
            if(temp && temp.value == card){
                flag = true;
                break;
            }
        }
        return flag;
    },

    // 检查能否吃牌
    checkChi: function(card) {
        var flag = false;
        if(card > 27){
            return flag;
        }
        for( var pos in this.cards){
            if(!this.cards.hasOwnProperty(pos)){
                continue;
            }
            var value1 = this.cards[pos];
            if(value1.num < 1){
                continue
            }
            var value2 = null;
            var value3 = null;
            pos = +pos;
            for(var i = pos+1; i < this.cards.length; i++){
                value2 = this.cards[i];
                if(!value2){
                    continue;
                }
                if(value2.num > 0){
                    // 4 5 6 ,这种情况， 要取三张牌
                    if(i + 1 <= this.cards.length){
                        value3 = this.cards[i + 1];
                    }
                    break;
                }
            }
            // 东南西北中发白不能吃
            if(!value2 || value1.num < 1 || value2.num < 1 || value1.value > 27 || value2.value > 27){
                continue;
            }
            // 不是一个花色不能吃
            if( parseInt((value1.value - 1) / 9) != parseInt((card - 1) / 9) || parseInt((value2.value - 1) / 9) != parseInt((card - 1) / 9)){
                continue;
            }
            if(card + 1 == value1.value && card + 2 == value2.value){
                flag = true;
                break;
            }
            if(value1.value + 1 == card && value1.value + 2 == value2.value){
                flag = true;
                break;
            }
            if(value1.value + 1 == value2.value && value1.value + 2 == card){
                flag = true;
                break;
            }
            // 前面两张检查完了，检查三张中card的夹中间的情况
            if(!value3 || value3.num < 1 || parseInt((value3.value - 1) / 9) != parseInt((card - 1) / 9)){
                continue;
            }
            if(value1.value + 1 == card && card + 1 == value3.value){
                flag = true;
                break;
            }
        }
        return flag;
    },
    gethandEffectiveCards : function () {
        var cards = [];
        for(var pos in this.cards){
            if(!this.cards.hasOwnProperty(pos)){
                continue;
            }
            if(this.cards[pos].num > 0){
                cards.push(this.cards[pos]);
            }
        }
        return cards;
    },

    getSynSettementHandCardDate:function () {
        return {
            cards:this.gethandEffectiveCards(),
            pengs:this.PENGs,
            gangs:this.GANGs,
            chiInfo:this.chiInfo,
        }
    },
    getSynGangCardDate :function () {
        return this.GANGs;
    },
};

///////////////////////////////////////////////////////////////////////////////
//>> 游戏玩家

function Player(owner, index) {
    this.owner          = owner;    // 房间对象
    this.index          = index;    // 玩家位置

    this.uid            = 0;        // 玩家ID
    this.info           = {};       // 玩家信息
    this.wsConn         = null;     // WebSocket连接对象
    this.online         = false;    // 玩家是否在线
    this.queuedPackets  = [];       // 数据包

    this.score          = 0;        // 积分
    this.roundScore     = 0;        // 本轮积分情况
    this.ready          = false;    // 玩家是否就绪
    this.handsCards     = null;     // 手牌
    this.playedCards    = [];       // 出的牌

    this.isHupai        = false;    // 是否胡牌
    this.huPaiMethod    = 0;        // 胡牌方式 1 自摸， 2 点炮
    this.mixCard        = 0;        // 当前房间混牌， 258做将时没有混牌
    this.settlementMarks= {};
    this.newMahjong     = {};       // 刚摸的牌
    this.huPaiType      = 0;        // 胡牌方式

    this.tips           = {
        gang: 0,
        peng: 0,
        chi : 0,
        hu: 0,
    };
    this.isErrorHu      = false;     // 错胡，限制没有胡上上家牌，却要胡上家的牌，
    this.isWindAll      = false;     // 胡牌十三幺风是否全
    this.huPaiMultiple  = 0;        // 胡牌翻数
    this.huCard         = 0;        // 胡牌的值

    this.dianPaoNum     = 0;        // 点炮次数
    this.ziMoNum        = 0;        // 自摸次数
    this.jiePaoNum      = 0;        // 接炮次数
    this.anGangNum      = 0;        // 暗杠次数
    this.mingGangNum    = 0;        // 明杠次数 （包括加杠）
}

Player.prototype = {

    // 初始化
    init: function(initArgs, wsConn) {
        this.uid = initArgs.uid;
        this.info.name = initArgs.name;
        this.info.headpic = initArgs.headpic;
        this.info.sex = initArgs.sex;
        this.wsConn = wsConn;
        this.wsConn.pushCloseHandler(function(){
            this.onConnClosed();
        }.bind(this));
        this.online = true;

        this.handsCards = new HandCards(this);

        this.playedCards = [];
        this.mixCard = 0;
        this.newMahjong = 0;
        this.roundScore = 0;    // 每局积分
    },

    exit: function() {
        this.uid = 0;
        this.ready = false;
        this.handsCards = null;
        this.online = false;
        this.wsConn.close();
        this.wsConn = null;
        this.mixCard = 0;
        this.newMahjong     = 0;       // 刚摸的牌
        this.huPaiType      = 0;        // 胡牌方式
        this.dianPaoNum     = 0;        // 点炮次数
        this.ziMoNum        = 0;        // 自摸次数
        this.jiePaoNum      = 0;        // 接炮次数
        this.anGangNum      = 0;        // 暗杠次数
        this.mingGangNum    = 0;        // 明杠次数 （包括加杠）
        this.settlementMarks = {};
        this.isHupai = false;
        this.huPaiScore = 0;
        this.isTingPai = false;
        this.isErrorHu = false;
        this.huPaiMultiple  = 0;        // 胡牌翻数
        this.huCard         = 0;        // 胡牌的值
    },

    // 新一轮游戏重置数据
    reset: function() {
        this.roundScore = 0;
        this.handsCards.reset();
        this.huPaiMethod = 0;
        this.isHupai = false;
        this.playedCards = [];
        this.mixCard = 0;
        this.newMahjong = 0;
        this.settlementMarks = {};
        this.huPaiType = 0;
        this.huPaiScore = 0;
        this.isErrorHu = false;
        this.isTingPai = false;
        this.clearTips();
        this.huPaiMultiple  = 0;        // 胡牌翻数
        this.huCard         = 0;        // 胡牌的值
    },

    destroy: function() {
        if (this.isInited()) {
            this.exit();
        }
    },

    onConnClosed: function() {
        if (this.online) {
            this.online = false;
            this.owner.onPlayerMsg(this, {
                code    : Player.MSG_PLAYER_OFFLINE,
                args    : {

                }
            });
        }
    },
    getHandCards: function() {
        return this.handsCards;
    },
    onPlayerResped: function() {
        // 清理缓存的包
        this.queuedPackets = [];
    },
    /**
     * 设置新连接
     * @param wsConn
     */
    setNewConn: function(wsConn) {
        this.wsConn = wsConn;
        this.wsConn.pushCloseHandler(function(){
            this.onConnClosed();
        }.bind(this));
        this.online = true;
    },

    onReconnect: function() {
        // 发送缓存的数据包
        if (this.queuedPackets.length > 0) {
            var clonedPackets = clone(this.queuedPackets);
            this.queuedPackets = [];

            setTimeout(function(){
                clonedPackets.forEach(function(msg){
                    this.sendMsg(msg.code, msg.args);
                }.bind(this));
            }.bind(this), 200);
        }
    },


    // 判断玩家是否已经初始化
    isInited: function() {
        return this.uid != 0;
    },


    isPlayer: function(uid) {
        return this.uid == uid;
    },
    isOnline:function(){
        return this.online;
    },

    isTing: function () {
        return this.isTingPai;
    },

    isHu: function () {
        return this.isHupai;
    },
    // 胡牌翻数
    sethuPaiMultiple:function (num) {
        this.huPaiMultiple  += num;
    },
    // 获取胡牌翻数
    gethuPaiMultiple:function () {
        return this.huPaiMultiple;
    },

    pushHuPaiType: function(type) {
        this.huPaiType = type;
    },
    pushHuPaiMethod: function(method) {
        this.huPaiMethod = method;
    },
    hasHuPaiMethod: function(method) {
        return (this.huPaiMethod == method);
    },
    getHuPaiMethod: function () {
        return this.huPaiMethod;
    },

    hasHuPaiType: function(type) {
        return (this.huPaiType == type);
    },
    getHuPaiType: function() {
        return this.huPaiType;
    },
    clearHuPaiType: function() {
        this.huPaiType = 0;
    },
    clearHuPaiMethod: function() {
        this.huPaiMethod = 0;
    },
    // 获取数据
    getInfo: function() {
        return {
            uid     : this.uid,
            name    : this.info.name,
            headpic : this.info.headpic,
            sex     : this.info.sex,
            ip      : this.wsConn.getAddrString(),

            online  : this.online,
            ready   : this.ready,
        };
    },

    // 获取重新连接数据
    getRecInfo: function(me) {
        var recArgs = {
            uid     : this.uid,
            name    : this.info.name,
            headpic : this.info.headpic,
            sex     : this.info.sex,

            online  : this.online,
            ready   : this.ready,
            handsCards : this.handsCards.getHandCardInfo(me),
            playedCards: this.playedCards,
            newMahjong  : this.newMahjong,
            score   : this.score,
        };
        if (this.online) {
            recArgs.ip = this.wsConn.getAddrString();
        }
        return recArgs;
    },
    decIntegral: function(what, num) {
        this.score -= num;
        this.roundScore -= num;

        if (!this.settlementMarks.hasOwnProperty(what)) {
            this.settlementMarks[what] = 0;
        }
        this.settlementMarks[what] -= num;
    },
    incIntegral: function(what, num) {
        this.score += num;
        this.roundScore += num;
        if (!this.settlementMarks.hasOwnProperty(what)) {
            this.settlementMarks[what] = 0;
        }
        this.settlementMarks[what] += num;
    },

    incHuPaiScore:function (winScore) {
        this.huPaiScore += winScore;
    },

    decHuPaiScore:function (failScore) {
        this.huPaiScore -= failScore;
    },

    setReady: function(ready) {
        this.ready = ready;
    },

    getReady: function() {
        return this.ready;
    },

    // 获取结算信息
    getSettementInfo: function() {
        return {
            name: this.info.name,
            headpic: this.info.headpic,
            multiple: this.gethuPaiMultiple(),
            score: this.roundScore,
            isYouJiao: this.isTingPai,
            huType: this.getHuPaiMethod(),
            huCard: this.huCard,
            handsCards: this.handsCards.getSynSettementHandCardDate(),
        }
    },

    setMixCard: function (mixCard) {
        this.mixCard = mixCard;
    },

    // 设置手牌
    setHandCards: function(cards) {
        var _me = this;

        _me.reset();

        _me.handsCards.adds(cards);
        _me.sendMsg(Opcodes.SMSG_SET_PLAYER_CARDS, _me.handsCards.getSync(true));
    },
    // 检查玩家是否听牌
    checkTingPai: function() {
        if (this.isHupai) {
            this.isTingPai = true;
            return;
        }
        if (CheckFunc.checkHearPai(this, this.owner.roomType, this.owner.selectWind)) {
            this.isTingPai = true;
        } else {
            this.isTingPai = false;
        }
    },
    /**
     * 设置刚摸的牌
     * @param card
     */
    setNewMahjong: function(card) {

        this.newMahjong = (card.type - 1) * 9 + card.value;

        this.isErrorHu = false;

        this.sendMsg(Opcodes.SMSG_SET_PLAYER_HAND_CARD, {
            cards: this.newMahjong,
            mixCard:    this.mixCard,
        });

        if (1 == this.owner.roomType) {
            if (this.checkRoomType1_Hupai(this.newMahjong)) {
                this.tips.hu = this.newMahjong;
            }
            this.tips.gang = this.checkRoomType1_Gang(this.newMahjong, true);
        }else if( 2 == this.owner.roomType){
            if (this.checkRoomType2_Hupai(this.newMahjong)) {
                this.tips.hu = this.newMahjong;
            }
            this.tips.gang = this.checkRoomType2_Gang(this.newMahjong, true);
        }

        this.sendTips();
    },

    // 检查能否杠牌
    checkRoomType1_Gang: function(card, me) {
        // 检查当前牌是否是混牌，
        if(card == this.mixCard){
            return 0;
        }
        // 检查手牌
        if (this.handsCards.hasSame(card) == 3) {
            return card;
        }

        if (me) {
            // 检查碰的牌
            if(this.handsCards.checkAddGang(card)){
                return card;
            }

            //检查手牌中有没有杠牌
            for (var key in this.handsCards.cards) {
                if (!this.handsCards.cards.hasOwnProperty(key)) {
                    continue;
                }

                if (this.handsCards.cards[key].num == 4 && this.handsCards.cards[key].value != this.mixCard) {
                    return this.handsCards.cards[key].value;
                }
            }
        }
        return 0;
    },
    // 检查能否杠牌
    checkRoomType2_Gang: function(card, me) {
        // 检查手牌
        if (this.handsCards.hasSame(card) == 3) {
            return card;
        }

        if (me) {
            // 检查碰的牌
            if(this.handsCards.checkAddGang(card)){
                return card;
            }

            //检查手牌中有没有杠牌
            for (var key in this.handsCards.cards) {
                if (!this.handsCards.cards.hasOwnProperty(key)) {
                    continue;
                }

                if (this.handsCards.cards[key].num == 4) {
                    return this.handsCards.cards[key].value;
                }
            }
        }
        return 0;
    },
    // 能否碰牌
    checkRoomType1_Peng: function(card) {
        // 检查当前牌是否是混牌，
        if(card == this.mixCard){
            return false;
        }
        return this.handsCards.checkPeng(card);
    },
    // 能否碰牌
    checkRoomType2_Peng: function(card) {
        return this.handsCards.checkPeng(card);
    },

    // 发送提示
    sendTips: function(isHu) {
        isHu = isHu || false;

        var tips = [];
        var card = 0;
        if (!isHu) {
            if (this.tips.gang != 0) {
                tips.push('gangpai');
                card = this.tips.gang;
            }
            if (this.tips.peng != 0) {
                tips.push('pengpai');
                card = this.tips.gang;
            }
            if (this.tips.chi != 0){
                tips.push('chi');
                card = this.tips.chi;
            }
        }
        if (this.tips.hu != 0) {
            tips.push('hupai');
            card = this.tips.hu;
        }

        if (tips.length > 0) {
            this.sendMsg(Opcodes.SMSG_SET_TIPS, {
                tips: tips,
                card: card,
            });

            ///////////////////// save playback date
            var index = this.owner.getPlayerIdx(this.uid);
            this.owner.playBackPage.push({
                code: Opcodes.SMSG_SET_TIPS,
                args: {
                    tips: tips,
                    card: card,
                    index: index,
                }
            });
            ////////////////////////////////////////
        }
    },

    clearTips: function () {
        this.tips.gang = 0;
        this.tips.peng = 0;
        this.tips.chi  = 0;
        this.tips.hu   = 0;
    },

    hasTip: function(name) {
        return this.tips[name] != 0;
    },

    hasAnyTip: function() {
        return this.tips.gang != 0 || this.tips.peng != 0 || this.tips.hu != 0 || this.tips.chi != 0;
    },
    // 发送消息
    sendMsg: function(code, msg) {
        var mThis = this;
        if (this.online) {
            this.wsConn.sendMsg({
                code:   code,
                args:   msg,
            });

            if (code != Opcodes.SMSG_BROADCAST_MESSAGE) {
                DEBUG(util.format("Send %d - \"%j\" To %d", code, msg, this.uid));
            }
        }else{
            // 缓存需要玩家响应的包
            mThis.queuedPackets.push({
                code:   code,
                args:   msg,
            });
        }
    },


    playCard: function(card) {
        var flag = false;
        if (card == this.newMahjong) {
            // 打的是刚摸的牌
            //this.playedCards.push(this.newMahjong);
            this.newMahjong = 0;
            flag = true;
        } else {
            // 检查玩家有没这张牌
            var numSame = this.handsCards.hasSame(card);
            if (numSame == 0) {
                return false;
            }
            // 减少一张出的手牌
            this.handsCards.decCard(card, 1);
            //this.playedCards.push(card);

            if (this.newMahjong != 0) {
                // 把摸得牌放进去
                this.handsCards.add(this.newMahjong);
                this.newMahjong = 0;
            }
            flag = true;
        }

        return flag;
    },

    pengCard: function () {

        if(!this.tips.peng || this.tips.peng != this.owner.curMahjong){
            return -1;
        }
        if(this.handsCards.hasSame(this.tips.peng) > 1) {
            var value = this.tips.peng;
            value = value || -1;
            this.handsCards.decCard(this.tips.peng, 2);

            this.handsCards.addPeng(this.tips.peng);

            this.clearTips();

            return value;
        }
        return -1;
    },

    chiCard: function (curMaJang, cards, owner) {
        var chiCard = -1;
        if(this.tips.chi && this.tips.chi == curMaJang && this.handsCards.hasEatCard(curMaJang, cards) === true) {

            // 从手牌中减掉吃牌，当前打出的牌不减去，本身就是不自己的
            if(curMaJang != cards.value1 ){
                this.handsCards.decCard(cards.value1, 1);
            }
            if(curMaJang != cards.value2 ){
                this.handsCards.decCard(cards.value2, 1);
            }
            if(curMaJang != cards.value3 ){
                this.handsCards.decCard(cards.value3, 1);
            }
            this.handsCards.addChi(cards, owner);
        }else{
            return chiCard;
        }
        chiCard = this.tips.chi;
        this.clearTips();

        return chiCard;
    },

    gangCard: function (owner,playerIndex) {

        if(!this.tips.gang){
            return null;
        }
        var value = this.tips.gang;
        var backBeltMark = 0;

        // 杠牌
        if (this.newMahjong != 0) {
            // 检查碰的牌
            var flag = false;
            for (var iPeng = 0; iPeng < this.handsCards.PENGs.length; ++iPeng) {
                var pengs = this.handsCards.PENGs[iPeng];
                if (pengs.value == this.newMahjong) {
                    flag = true;
                }
            }
            if(flag){
                // 加杠
                this.newMahjong = 0;
                backBeltMark = Enum.PlayerMark.PLAYER_TIP_JG;
                this.handsCards.decPengCard(value);
            }else{
                // 暗杠
                if(this.newMahjong == value){
                    // 杠的刚摸起来的牌
                    this.newMahjong = 0;
                    this.handsCards.decCard(value, 3);
                }else{
                    // 杠的手中的牌
                    this.handsCards.decCard(value, 4);
                    // 把刚摸起来的牌放入手中
                    this.handsCards.add(this.newMahjong, 1);
                }
                backBeltMark = Enum.PlayerMark.PLAYER_TIP_AG;
            }
        }else {
            // 杠别人的牌
            // 明杠
            backBeltMark = Enum.PlayerMark.PLAYER_TIP_MG;
            this.handsCards.decCard(value, 3);
        }

        this.handsCards.addGang(this.tips.gang, backBeltMark, owner);

        this.clearTips();

        return {
            card:value,
            mark:backBeltMark,
            playerIndex: playerIndex,
        };
    },

    myHuCard: function() {
        var me = false;
        var flag = false;
        // 自摸
        if(this.newMahjong != 0){
            me = true;
        }
        if(1 == this.owner.roomType){
            flag = this.playerType1_Hupai(this.tips.hu, me) === true ? true : false;
        }else if(2 == this.owner.roomType) {
            flag = this.playerType2_Hupai(this.tips.hu, me) === true ? true : false;
        }
        if(flag){
            if(me){
                this.ziMoNum += 1;
            }else {
                this.jiePaoNum += 1;
            }
            this.huCard = this.tips.hu
            this.isHupai = true;
        }
        return flag;
    },

    // 生成战报
    buildReport: function(roomId, time) {
        return {
            uid     : this.uid,
            time    : time,
            roomId  : roomId,
            score   : this.score,
        };
    },

    ///////////////////////////////////////////////////////////////////////////

    playerType1_Hupai: function (card, me) {
        var huPaiType = CheckFunc.checkType1_Hupai(this, card);
        if(huPaiType != 0){
            this.pushHuPaiType(huPaiType);
            if (me) {
                // 自摸
                this.pushHuPaiMethod(Enum.HupaiMethod.METHOD_ZIMO_PAIRS);
                //}
            } else {
                // 别人点炮
                this.pushHuPaiMethod(Enum.HupaiMethod.METHOD_DIANPAO_PAIRS);
            }
            return true;
        }
        return false;
    },

    playerType2_Hupai: function (card, me) {
        var huPaiType = CheckFunc.checkType2_Hupai(this, card);
        if(huPaiType != 0){
            this.pushHuPaiType(huPaiType);
            if (me) {
                // 自摸
                this.pushHuPaiMethod(Enum.HupaiMethod.METHOD_ZIMO_PAIRS);
            } else {
                // 别人点炮
                this.pushHuPaiMethod(Enum.HupaiMethod.METHOD_DIANPAO_PAIRS);
            }
            return true;
        }
        return false;
    },
    // 带混模式  检查能否胡牌
    checkRoomType1_Hupai: function(card) {
        return CheckFunc.checkType1_Hupai(this, card);
    },

    // 258做将模式  检查能否胡牌
    checkRoomType2_Hupai: function(card) {
        return CheckFunc.checkType2_Hupai(this, card);
    },
    /**
     * 根据其他玩家当前出的牌检查自己能否碰/杠/吃等
     * @param card      牌
     * @param sPlayer   出牌的玩家
     */
    checkWithPlayedPubCard: function(card) {
        var myThis = this;
        var flag = false;

        // 带混类型时混牌不能打出
        if(1 == this.owner.roomType && card == this.mixCard){
            return false;
        }
        // 清除胡牌标志
        this.clearHuPaiMethod();
        this.clearHuPaiType();
        // 清除提示重新检查
        this.clearTips();
        if(myThis.owner.roomType == 1){
            flag = myThis.checkRoomType1_PlayedCard(card);
        }else if(myThis.owner.roomType == 2){
            flag = myThis.checkRoomType2_PlayedCard(card);
        }
        return flag;
    },
    // 带混   检查提示
    checkRoomType1_PlayedCard: function (card) {
        var myThis = this;
        var flag = false;
        // 检查能否胡牌, 没有混带才能平胡
        if(!myThis.handsCards.hasSame(this.mixCard) && !this.isErrorHu) {
            if(CheckFunc.checkType1_Hupai(this, card)){
                myThis.tips.hu = card;
                flag = true;
            }
        }
        // 检查能否杠牌
        myThis.tips.gang = myThis.checkRoomType1_Gang(card, false);
        flag = myThis.tips.gang ? true : flag;
        // 检查能否碰牌
        if(myThis.checkRoomType1_Peng(card)){
            myThis.tips.peng = card;
            flag = true;
        }
        // 带混模式不能吃牌

        return flag;
    },

    // 258做将  检查提示
    checkRoomType2_PlayedCard: function (card) {
        var myThis = this;
        var flag = false;
        if(!myThis.isErrorHu) {
            if (CheckFunc.checkType2_Hupai(this, card)) {
                myThis.tips.hu = card;
                flag = true;
            }
        }
        myThis.tips.gang = myThis.checkRoomType2_Gang(card, false);
        flag = myThis.tips.gang ? true : flag;

        if(myThis.checkRoomType2_Peng(card)){
            myThis.tips.peng = card;
            flag = true;
        }
        // 258做将模式可选能吃牌
        if(this.owner.selectIsEat) {
            var thisIdx = this.owner.getPlayerIdx(this.uid);
            var playIdx = this.owner.curPlay;
            // 吃牌只能吃上家的
            if((thisIdx == 1 && 4 == playIdx) || thisIdx == playIdx + 1){
                if (myThis.handsCards.checkChi(card)) {
                    myThis.tips.chi = card;
                    flag = true;
                }
            }
        }
        return flag;
    },
};

Player.MSG_CAN_HUPAI        = 100;  // 玩家能胡牌
Player.MSG_PENG_CARD        = 101;  // 玩家出牌
Player.MSG_PENG_CARD        = 102;  // 玩家碰牌
Player.MSG_PENG_CARD        = 103;  // 玩家杠牌
Player.MSG_CHI_CARD         = 104;  // 玩家吃牌
Player.MSG_CHI_CARD         = 105;  // 玩家过牌
Player.MSG_HU_CARD          = 106;  // 玩家胡牌
Player.MSG_PLAYER_OFFLINE   = 107;  // 玩家离线

exports.Player = Player;